package com.appshelves.model;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import com.appshelves.R;
import com.appshelves.model.saveable.Changeable;
import com.appshelves.model.saveable.ChangeableList;
import com.appshelves.utils.ComponentHelper;
import com.appshelves.utils.Profiler;
import com.appshelves.utils.Utils;

public class AppData extends Changeable<AppData> { // stores the unchangeable data.
    public String label;
    public Bitmap smallTexture;
    private App app;

    AppData(ChangeableList<AppData> list, ResolveInfo info) {
        super(list);

        initByInfo(info);
    }

    void initByInfo(ResolveInfo info) {
        PackageManager packageManager = ComponentHelper.getPackageManager();
        Profiler p = new Profiler(this, "data from packagemanager");
        label = info.loadLabel(packageManager).toString();
        Bitmap icon = getIconBitmap(info, packageManager);
        p.e();

        smallTexture = Utils.createSmallTexture(icon, label);

        markListChanged();
    }

    void bindApp(App app) {
        this.app = app;
    }

    App getApp() {
        return app;
    }

    /// Bitmap manipulation.

    private Bitmap getIconBitmap(ResolveInfo info, PackageManager packageManager) {
        Drawable icon = getFullResIcon(info, packageManager);
        if (!(icon instanceof BitmapDrawable))
            return null; // TODO not a BitmapDrawable
        return ((BitmapDrawable) icon).getBitmap();
    }

    private Drawable getFullResDefaultActivityIcon() {
        return Utils.getContext().getResources().getDrawable(R.drawable.ic_launcher);
    }

    private Drawable getFullResIcon(Resources resources, int iconId) {
        Drawable d;
        try {
            d = resources.getDrawable(iconId);
        } catch (Resources.NotFoundException e) {
            d = null;
        }

        return (d != null) ? d : getFullResDefaultActivityIcon();
    }

    private Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) {
        Resources resources;
        try {
            resources = packageManager.getResourcesForApplication(info.activityInfo.applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            resources = null;
        }
        if (resources != null) {
            int iconId = info.activityInfo.getIconResource();
            if (iconId != 0)
                return getFullResIcon(resources, iconId);
        }
        return getFullResDefaultActivityIcon();
    }

    //// Serialization mechanism. 

    public AppData() { // public cauz serialization is in another package
    }

    private void serializeBitmap(DataOutputStream stream) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        smallTexture.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
        byte imageByteArray[] = byteStream.toByteArray();
        stream.writeInt(imageByteArray.length);
        stream.write(imageByteArray);

    }

    private Bitmap deserializeBitmap(DataInputStream stream) throws IOException {
        final int length = stream.readInt();

        final byte[] imageByteArray = new byte[length];
        stream.read(imageByteArray);
        return BitmapFactory.decodeByteArray(imageByteArray, 0, length);
    }

    @Override
    protected void writeToStream(DataOutputStream stream) throws IOException {
        stream.writeUTF(label);
        serializeBitmap(stream);
    }

    @Override
    protected void readFromStream(DataInputStream stream) throws IOException {
        label = stream.readUTF();
        smallTexture = deserializeBitmap(stream);
    }

}
